package org.helgoboss.bundle_project_generator

import java.io.File
import org.helgoboss.project_data.ProjectData
import org.helgoboss.scala_additions.{FileTree, RichFile}
import org.helgoboss.scala_additions.Implicits._
import java.nio.file.Files

object BundleProjectGenerator {
    /**
     * Takes the given project data and generates a Maven project resembling a bundle in the given target directory.
     * Requires the existence of the target directory.
     *
     * @param linkSourceFile if true, creates a symbolic link to the source code file instead of creating
     *        a new file containing the source code. Very useful for editing the source file in an IDE as a Maven project.
     *        projectData#sourceFile has to be set for this to work.
     */
    def generateBundleProject(projectData: ProjectData, targetDir: File, linkSourceFile: Boolean = false) {
        val newSourceFileName = generateNewSourceFileName(projectData)
    
        generateBundleProjectInternal(projectData, targetDir, newSourceFileName) { file =>
            if (linkSourceFile) {
                require(projectData.sourceFile.isDefined)
                Files.createLink(file.toPath, projectData.sourceFile.get.toPath)
            } else {
                file.content = projectData.sourceCode
            }
        }
    }
    
    private def generateNewSourceFileName(projectData: ProjectData) = projectData.sourceFile match {
        case Some(sourceFile) => sourceFile.getName
        case None => "code.scala"
    }

    /**
     * Like {@link #generateBundleProject}, but only generates "pom.xml".
     */
    def generateBundleProjectPom(projectData: ProjectData, targetDir: File) {
        targetDir.mkdirs()
        val pomFile = targetDir / "pom.xml"
        pomFile.content = generatePom(projectData, generateNewSourceFileName(projectData)).toString()
    }
    
    private def generateBundleProjectInternal(projectData: ProjectData, targetDir: File, newSourceFileName: String)(f: File => Any) {
        new FileTree {
            def structure = {
                "pom.xml" << generatePom(projectData, newSourceFileName).toString
                "src" << {
                    "main" << {
                        "scala" << {
                            newSourceFileName << f
                        }
                    }
                }
            }
        }.createIn(targetDir)
    }
    
    private def generatePom(projectData: ProjectData, newSourceFileName: String) = {
        <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    

            <modelVersion>4.0.0</modelVersion>
            {
                projectData.parentProjectId.map { v =>
                    <parent>
                        <groupId>{v.groupId}</groupId>
                        <artifactId>{v.artifactId}</artifactId>
                        <version>{v.version}</version>
                    </parent>
                }.orNull
            }
            <artifactId>{projectData.projectId.artifactId}</artifactId>
            <version>{projectData.projectId.version}</version>
            <packaging>bundle</packaging>
            {projectData.name.map(n => <name>{n}</name>).orNull}
            {projectData.description.map(d => <description>{d}</description>).orNull}
            <dependencies>
                {
                    projectData.dependencies.map { v =>
                        <dependency>
                            <groupId>{v.groupId}</groupId>
                            <artifactId>{v.artifactId}</artifactId>
                            <version>{v.version}</version>
                            <type>{v.`type`}</type>
                        </dependency>
                    }
                }
            </dependencies>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.scala-tools</groupId>
                        <artifactId>maven-scala-plugin</artifactId>
                        <version>2.14</version>
                        <configuration>
                            {projectData.dependencies.find(_.artifactId == "scala-library").map(d => <scalaVersion>{d.version}</scalaVersion>).orNull}
                        </configuration>
                        <executions>
                            <execution>
                                <phase>process-resources</phase>
                                <goals>
                                    <goal>compile</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                    <plugin>
                        <groupId>org.helgoboss</groupId>
                        <artifactId>maven-commandlet-client</artifactId>
                        <version>0.1-SNAPSHOT</version>
                        <executions>
                            <execution>
                                <phase>clean</phase>
                                <goals>
                                    <goal>execute-commandlet</goal>
                                </goals>
                            </execution>
                        </executions>
                        <configuration>
                            <commandletId>org.helgoboss.one-filer</commandletId>
                            <arguments>
                                <argument>--mode</argument>
                                <argument>generate-pom</argument>
                                <argument>--source</argument>
                                <argument>${{project.basedir}}/src/main/scala/{newSourceFileName}</argument>
                                <argument>--targetDir</argument>
                                <argument>${{project.basedir}}</argument>
                            </arguments>
                        </configuration>
                    </plugin>
                    <plugin>
                        <groupId>org.apache.felix</groupId>
                        <artifactId>maven-bundle-plugin</artifactId>
                        <version>2.3.5</version>
                        <configuration>
                            <instructions>
                                {projectData.bundleActivator.map(a => <Bundle-Activator>{a}</Bundle-Activator>).orNull}
                            </instructions>
                        </configuration>
                    </plugin>
                </plugins>
            </build>
        </project>
    }
}